package engine.core
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.text.*;
	
	import game.network.*;
	
	public class RxCommandConsole extends RxTextConsole
	{
		private var m_stage:Stage;
		protected var m_commands:Vector.<String>;
		protected var m_historyIndex:int;
		protected var m_commandFunctionMap:Object;
		protected var m_commandDescriptionMap:Object;
		protected var m_commandUsageMap:Object;
		private static const SMALL_WIDTH:int = 400;
		private static const SMALL_HEIGHT:int = 160;
		private static const BIG_WIDTH:int = 880;
		private static const BIG_HEIGHT:int = 768;
		private static var s_instance:RxCommandConsole;
		private static const helpDescription:String = "Get help on console commands";
		private static const helpUsage:String = "are you serious?";
		private static const exitUsage:String = "Close the command console";
		private static const bigUsage:String = "Display expanded console";
		private static const smallUsage:String = "Display reduced console";
		private static const clsUsage:String = "Clear console";
		private static const logDescription:String = "View or modify console logging level";
		private static const logUsage:String = "log        - displays current console logging level\n" + "log level  - sets console logging level\n";
		private static const stageDescription:String = "Set stage parameters";
		private static const stageUsage:String = "stage quality                         - displays current stage quality level\n" + "stage quality [low|medium|high|best]  - sets stage quality level\n" + "stage framerate                       - shows current stage framerate\n" + "stage framerate value                 - sets stage framerate to value (1 to 1000)\n";

		public function RxCommandConsole(style:String, stage:Stage)
		{
			super(style, stage);
			s_instance = this;
			this.m_stage = stage;
			SetRect(new Rectangle(0, 0, SMALL_WIDTH, SMALL_HEIGHT));
			OnStageResize(null);
			this.m_historyIndex = 0;
			this.m_commands = new Vector.<String>;
			this.m_commandFunctionMap = new Object();
			this.m_commandDescriptionMap = new Object();
			this.m_commandUsageMap = new Object();
			this.SetCommandFunction("help", helpDescription, helpUsage, new RxCallback(this.HelpCommand));
			this.SetCommandFunction("exit", exitUsage, exitUsage, new RxCallback(this.ExitCommand));
			this.SetCommandFunction("big", bigUsage, bigUsage, new RxCallback(this.BigCommand));
			this.SetCommandFunction("small", smallUsage, smallUsage, new RxCallback(this.SmallCommand));
			this.SetCommandFunction("cls", clsUsage, clsUsage, new RxCallback(this.clsCommand));
			stage.addEventListener(Event.RESIZE, this.OnStageResize);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, this.OnStageKeyDown);
			var textFiled:TextField = GetInput().GetTextField();
			textFiled.addEventListener(KeyboardEvent.KEY_UP, this.OnTextKeyUp);
		}
		
		private function OnStageResize(event:Event) : void
		{
			var rectangle:Rectangle = GetRect();
			SetRect(new Rectangle(0, (GetStage().stageHeight - 1) - rectangle.height, rectangle.width, rectangle.height));
		}
		
		public function SetCommandFunction(type:String, info:String, str:String, callback:RxCallback) : void
		{
			type = type.toLowerCase();
			this.m_commandFunctionMap[type] = callback;
			this.m_commandDescriptionMap[type] = info;
			this.m_commandUsageMap[type] = str;
		}
		
		public function GetCommandFunction(param1:String) : RxCallback
		{
			var _loc_2:* = param1.toLowerCase();
			return this.m_commandFunctionMap[_loc_2];
		}
		
		public function GetCommandString(param1:int) : String
		{
			if (param1 < 0)
			{
				param1 = this.m_commands.length + param1;
			}
			return this.m_commands[param1];
		}
		
		override protected function OnInput(param1:String) : void
		{
			var _loc_3:String = null;
			var _loc_4:String = null;
			var _loc_5:Array = null;
			var _loc_6:RxCallback = null;
			if (param1.length > 0)
			{
				this.m_commands.push(param1);
			}
			var _loc_2:* = param1.split(";");
			for each (_loc_3 in _loc_2)
			{
				
				if (_loc_3.length > 0)
				{
					Write(">" + _loc_3 + "\n");
					_loc_4 = RxUtilities.CleanupWhitespaces(_loc_3);
					_loc_5 = _loc_4.split(" ");
					_loc_5[0] = _loc_5[0].toLowerCase();
					_loc_6 = this.m_commandFunctionMap[_loc_5[0]];
					if (_loc_6 != null)
					{
						_loc_6.m_function(_loc_5);
						continue;
					}
					Write("ERROR: unknown command \"" + _loc_5[0] + "\"\n");
				}
			}
			super.OnInput(param1);
			this.m_historyIndex = 0;
		}
		
		private function AutoComplete(param1:String) : String
		{
			var _loc_3:String = null;
			var _loc_4:int = 0;
			if (param1 == "")
			{
				return "";
			}
			var _loc_2:* = param1.toLowerCase();
			for (_loc_3 in this.m_commandFunctionMap)
			{
				
				_loc_4 = _loc_3.indexOf(_loc_2);
				if (_loc_4 == 0)
				{
					return _loc_3;
				}
			}
			return "";
		}
		
		private function HelpCommand(arr:Array) : void
		{
			var _loc_2:Array = null;
			var _loc_3:String = null;
			var _loc_4:String = null;
			var _loc_5:String = null;
			if (arr.length == 1)
			{
				_loc_2 = new Array();
				for (_loc_3 in this.m_commandFunctionMap)
				{
					
					_loc_2.push(_loc_3);
				}
				_loc_2.sort();
				Write("type \'help command\' for detailed help on a command:\n");
				for each (_loc_3 in _loc_2)
				{
					
					Write(" " + _loc_3 + " - " + this.m_commandDescriptionMap[_loc_3] + "\n");
				}
				Write("\n");
			}
			else
			{
				_loc_4 = arr[1].toLowerCase();
				_loc_5 = this.m_commandUsageMap[_loc_4];
				if (_loc_5 != null)
				{
					Write(_loc_5 + "\n");
				}
				else
				{
					Write("ERROR: unknown command \"" + arr[1] + "\"\n");
				}
			}
		}
		
		private function ExitCommand(param1:Array) : void
		{
			SetVisible(false);
		}
		
		private function BigCommand(param1:Array) : void
		{
			SetRect(new Rectangle(0, (GetStage().stageHeight - 1) - BIG_HEIGHT, BIG_WIDTH, BIG_HEIGHT));
		}
		
		private function SmallCommand(param1:Array) : void
		{
			SetRect(new Rectangle(0, (GetStage().stageHeight - 1) - SMALL_HEIGHT, SMALL_WIDTH, SMALL_HEIGHT));
		}
		
		private function clsCommand(param1:Array) : void
		{
			ClearOutput();
		}
		
		private function OnStageKeyDown(event:KeyboardEvent) : void
		{
			//if (RxTransactionServer.instance.hasQAPermission())
			if (true)
			{
				if (event.keyCode == RxKeyboard.KEY_F2)
				{
					SetVisible(!GetVisible());
					event.stopImmediatePropagation();
				}
			}
		}
		
		public function OnTextKeyUp(e:KeyboardEvent) : void
		{
			switch(e.keyCode)
			{
				case RxKeyboard.KEY_ARROW_UP:
				case RxKeyboard.KEY_ARROW_DOWN:
				{
					SetInputSelection(-1, -1);
					break;
				}
				default:
				{
					break;
				}
			}
			
			e.stopImmediatePropagation();
		}
		
		override protected function OnTextKeyDown(event:KeyboardEvent) : void
		{
			var _loc_2:String = null;
			switch(event.keyCode)
			{
				case RxKeyboard.KEY_F2:
				{
					SetVisible(false);
					break;
				}
				case RxKeyboard.KEY_ARROW_UP:
				{
					this.m_historyIndex = this.m_historyIndex - 1;
					if (this.m_historyIndex >= -this.m_commands.length)
					{
						SetInputText(this.GetCommandString(this.m_historyIndex));
					}
					else
					{
						this.m_historyIndex = -this.m_commands.length;
					}
					break;
				}
				case RxKeyboard.KEY_ARROW_DOWN:
				{
					this.m_historyIndex = this.m_historyIndex + 1;
					if (this.m_historyIndex < 0)
					{
						SetInputText(this.GetCommandString(this.m_historyIndex));
					}
					else
					{
						this.m_historyIndex = -1;
					}
					break;
				}
				case RxKeyboard.KEY_TAB:
				{
					_loc_2 = this.AutoComplete(GetInputText());
					if (_loc_2.length > 0)
					{
						SetInputText(_loc_2);
					}
					break;
				}
				default:
				{
					super.OnTextKeyDown(event);
					break;
				}
			}
			event.stopImmediatePropagation();
		}
		
		public function LogListener(index:int, s_name:String, arg:String, s_stack:String, bol:Boolean) : void
		{
			var str:String = "[" + arg + "] " + RxLog.GetLevelString(index) + ": " + s_name + "\n";
			if (s_stack)
			{
				str = str + (s_stack + "\n");
			}
			
			Write(str);
		}
		
		private function logCommand(param1:Array) : void
		{
			var _loc_2:int = 0;
			var _loc_3:int = 0;
			var _loc_4:String = null;
			var _loc_5:int = 0;
			if (param1.length == 1)
			{
				_loc_2 = RxLog.GetLevel(RxCommandConsole.instance.LogListener);
				_loc_3 = 0;
				while (_loc_3 < RxLog.NUM_LEVELS)
				{
					
					if (_loc_3 == _loc_2)
					{
						Write("*");
					}
					else
					{
						Write(" ");
					}
					Write(RxLog.GetLevelString(_loc_3) + "\n");
					_loc_3++;
				}
			}
			else
			{
				_loc_4 = String(param1[1]).toUpperCase();
				_loc_5 = 0;
				while (_loc_5 < RxLog.NUM_LEVELS)
				{
					
					if (_loc_4 == RxLog.GetLevelString(_loc_5).toUpperCase())
					{
						RxLog.SetLevel(RxCommandConsole.instance.LogListener, _loc_5);
						return;
					}
					_loc_5++;
				}
				Write("Unknown log level \'" + param1[1] + "\'\n");
			}
		}
		
		private function stageCommand(param1:Array) : void
		{
			var _loc_2:String = null;
			var _loc_3:int = 0;
			if (param1.length == 1)
			{
				Write(stageUsage);
				return;
			}
			switch(param1[1])
			{
				case "quality":
				{
					if (param1.length == 2)
					{
						_loc_2 = RxStage.stage.quality;
						Write("Stage quality is " + _loc_2.toUpperCase() + "\n");
					}
					else
					{
						_loc_2 = param1[2];
						switch(_loc_2)
						{
							case "low":
							{
								RxStage.stage.quality = StageQuality.LOW;
								break;
							}
							case "medium":
							{
								RxStage.stage.quality = StageQuality.MEDIUM;
								break;
							}
							case "high":
							{
								RxStage.stage.quality = StageQuality.HIGH;
								break;
							}
							case "best":
							{
								RxStage.stage.quality = StageQuality.BEST;
								break;
							}
							default:
							{
								break;
							}
						}
					}
					break;
				}
				case "framerate":
				{
					if (param1.length == 2)
					{
						_loc_3 = RxStage.stage.frameRate;
						Write("Stage framerate is " + _loc_3 + "fps\n");
					}
					else
					{
						_loc_3 = int(param1[2]);
						if (_loc_3 < 1 || _loc_3 > 1000)
						{
							Write(param1[2] + " is not a valid framerate\n");
						}
						else
						{
							RxStage.stage.frameRate = _loc_3;
						}
					}
					break;
				}
				default:
				{
					Write("Unknown command " + param1[1]);
					break;
				}
			}
		}
		
		public static function get instance() : RxCommandConsole
		{
			return s_instance;
		}
	}
}